﻿#pragma once

#include <boost/ptr_container/ptr_vector.hpp>
#include "CardControl.h"
#include "../../../utils/gui/Control.h"
#include "../../../utils/gui/Label.h"
#include "../../../domain/models/Card.h"
#include "../../../domain/models/CardsCollection.h"

namespace Views {
	namespace Helpers {
		namespace Graphic {
			/**
			* Grupa kontrolek dla kart. Pozwala na łatwe utworzenie 
			* wielu kontrolek dla podanej kolekcji kart jednego typu i podłączenie zdarzenia,
			* które zostanie wywołane po kliknięciu jednej z nich
			* @param TControl typ kontrolki karty
			* @param TCollection typ kolekcji kart
			* @param TCard typ karty
			*/
			template<typename TControl, typename TCollection, typename TCard>
			class CardsGroup: public Utils::GUI::Control
			{
				TCollection& cards;
				std::vector<TControl*> buttons;
				bool selectable;
			protected:
				/**
				* Typ zdarzenia wybrania karty
				* @param card Wybrana karta
				*/
				typedef boost::signal<void (TCard*)> OnCardPick;
				OnCardPick cardPickEvent; /**< Zdarzenie wybrania karty */

			public:
				/**
				* Inicjalizuje grupę kart, domyślnie nie można jej zaznaczać
				* @param cards Karty, dla których zostanie utworzona grupa kontrolek
				*/
				CardsGroup(TCollection& cards)
					: cards(cards), selectable(false)
				{
					createButtons();
				}

				/**
				* @param cards Karty, dla których zostanie utworzona grupa kontrolek
				* @param selectable Jeśli prawda, można zaznaczyć jedną z kart
				*/
				CardsGroup(TCollection& cards, bool selectable)
					: cards(cards), selectable(selectable)
				{
					createButtons();
				}

				/**
				* Tworzy kontrolkę dla każdej z kart
				*/
				void createButtons()
				{
					float pos = 10.;
					float width = 0;
					for (TCollection::iterator i = cards.begin(); i != cards.end(); ++i)
					{
						TControl* Button = new TControl(*i);
						Button->setSelectable();
						Button->Move(10., pos);
						pos += Button->GetHeightF() + 5.f;
						width = Button->GetWidthF();
						Button->doOnClick(boost::bind(&CardsGroup<TControl, TCollection, TCard>::CardClick, this, Button));
						buttons.push_back(Button);
						addChild(Button);
					}
					Shape = sf::Shape::Rectangle(0, 0, 10 + width + 10, 10 + pos - 5, sf::Color(242, 231, 172));
				}

				/**
				* Podłącza slot do sygnału wyzwalanego po wybraniu jednej z kart (jeśli karty można wybierać).
				* @param slot Funkcja wywoływana po wybraniu karty
				*/
				boost::signals::connection doOnCardPick(const boost::function<void (TCard*)>& slot)
				{
					return cardPickEvent.connect(slot);
				}

				/**
				* Wywołuje zdarzenie kliknięcia dla podanej kontrolki.
				* Jeśli kontrolki można zaznaczać, zostanie wywołane cardPickEvent
				* @param card_control Kliknięta kontrolka
				*/
				void CardClick(TControl* card_control)
				{
					if (selectable)
					{
						for (std::vector<TControl*>::iterator i = buttons.begin(); i != buttons.end(); ++i)
						{
							(*i)->unselect();
						}
						card_control->select();
					}
					Draw(true);
					cardPickEvent(card_control->getCard());
				}
			};

			typedef CardsGroup<PlayerCardControl, Cards::PlayersCards, Cards::PlayerCard> PlayersCardsGroup;
			typedef CardsGroup<WeaponCardControl, Cards::WeaponsCards, Cards::WeaponCard> WeaponsCardsGroup;
			typedef CardsGroup<RoomCardControl, Cards::RoomsCards, Cards::RoomCard> RoomsCardsControl;
		}
	}
}

